﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AForge.Neuro;
using AForge.Neuro.Learning;

namespace XOR
{
    class Program
    {
        static void Main(string[] args)
        {
            ActivationNetwork n = new ActivationNetwork(new SigmoidFunction(1.0), 2, 2, 1);
            BackPropagationLearning bpl = new BackPropagationLearning(n);
            bpl.LearningRate = 0.3;
            bpl.Momentum = 0.0;
            Console.WriteLine(bpl.Momentum);

            double[][][][] weights = new double[3][][][] {
                                                        new double[2][][] { new double[2][] { new double[] { 0.3, -0.1}, new double[] { -0.6,  0.9}},
                                                                            new double[2][] { new double[] {0.75}, new double[] {-0.23} }},
                                                        new double[2][][] { new double[2][] { new double[] { 0.7, -0.71}, new double[] { 0.6,  -0.9}},
                                                                            new double[2][] { new double[] {0.15}, new double[] {-0.83} }},
                                                        new double[2][][] { new double[2][] { new double[] { 0.93, -0.01}, new double[] { -0.006,  -0.9}},
                                                                            new double[2][] { new double[] {-0.5}, new double[] {0.567} }},
            };
            double[][][] biases = new double[3][][] {
                                                        new double[2][] {new double[] {0.23, -0.34}, new double[] {0.5}},
                                                        new double[2][] {new double[] {0.723, -0.134}, new double[] {0.25}},
                                                        new double[2][] {new double[] {-0.423, 0.934}, new double[] {-0.75}}
            };

            double[][] inputs = new double[4][] { new double[] {1,0},
                                                    new double[] {1,1},
                                                    new double[] {0,0},
                                                    new double[] {0,1}
            };
            double[][] outputs = new double[4][] {
                                                new double[]{1},
                                                new double[]{0},
                                                new double[]{0},
                                                new double[]{1}
            };

            for (int wN = 0; wN < weights.Length; wN++)
            {
                double[][][] layers = weights[wN];
                for (int layerI = 0; layerI < layers.Length; layerI++)
                {
                    double[][] connections = layers[layerI];
                    for (int connctionI = 0; connctionI < connections.Length; connctionI++)
                    {
                        double[] neurons = connections[connctionI];
                        for (int neuronI = 0; neuronI < neurons.Length; neuronI++)
                        {
                            n[layerI][neuronI][connctionI] = 0.0;// = connections[connectionI];
                            n[layerI][neuronI].Threshold = biases[wN][layerI][neuronI];
                        }
                        
                    }
                }

                for (int i = 0; i < 4000000; i++)
                {
                    double err = bpl.RunEpoch(inputs, outputs);
                    if (i % 1000 == 0)
                    {
                        Console.WriteLine(err);
                        ConsoleKeyInfo key = Console.ReadKey();
                        if (key.Key == ConsoleKey.Escape) break;
                    }
                }
                Console.WriteLine("Test");
                for (int i = 0; i < inputs.Length; i++)
                {
                    double[] output = n.Compute(inputs[i]);
                    for (int j = 0; j < outputs[0].Length; j++)
                    {
                        Console.Write(output[j]);
                    }
                    Console.WriteLine();
                }
                Console.ReadKey();
            }
        }
    }
}
